﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CodeMonkey.EditableObject.Descriptor
{
    //以下信息来自MSDN
    //当要访问 TypeDescriptor 信息并且您具有对象的实例时，应使用调用组件的方法。 只有当您不具有对象的实例时，才能使用调用类类型的方法。
    //为了提高速度，将由 TypeDescriptor 缓存属性和事件。 通常，它们在对象的生存期内保持不变。
    public sealed class EditableTypeDescriptor : CustomTypeDescriptor
    {
        #region  注解
        //因为该TypeDescriptor附着的类型ModelBase[T]实现了INotifyPropertyChanged接口;
        //所以我认为该TypeDescriptor就只需要为T[即底层的Model]提供描述就行了

        #endregion

        private PropertyDescriptorCollection propertiesInModel;

        public EditableTypeDescriptor(Type type, object instance) //instance就是EditableTypeDescriptor所附加的那个实例
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (type.GetInterface("IEditableObject") == null)
            {
                throw new ArgumentException(string.Format("类型{0}必须支持IEditableObject接口", type));
            }

            #region 从附着的类ModelBase[T]中取得T中的PropertyInfo ;赋值给m_PropertiesInGenericType;用于向Binding提供属性
            Type[] GenericArgumentTypesInModelBase = type.BaseType.GetGenericArguments();
            if (GenericArgumentTypesInModelBase == null)
            {
                throw new ArgumentException(string.Format("类型{0}必须为泛型类型", type.BaseType.Name));
            }
            PropertyInfo[] propInfosInModel = GenericArgumentTypesInModelBase[0].GetProperties();
            propertiesInModel = new PropertyDescriptorCollection(new PropertyDescriptor[] { });
            Array.ForEach(propInfosInModel, item => { propertiesInModel.Add(new TransacablePropertyDescriptor(item)); });
            #endregion
        }


        //返回此类型说明符所表示的对象的已筛选属性描述符的集合。 ----该解释来自于基类CustomTypeDescriptor的GetProperties()方法
        public override PropertyDescriptorCollection GetProperties()
        {
            var properties = new PropertyDescriptor[propertiesInModel.Count];
            propertiesInModel.CopyTo(properties, 0);
            return new PropertyDescriptorCollection(properties);//返回一个全新的PropertyDescriptorCollection;而不是一个执行私有字段指针
        }
    }

}
